package org.jeecg.modules.online.desform.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtil;
import org.apache.poi.ss.usermodel.Workbook;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.system.api.ISysBaseAPI;
import org.jeecg.common.system.query.QueryGenerator;
import org.jeecg.common.system.util.JwtUtil;
import org.jeecg.common.system.vo.DictModel;
import org.jeecg.common.util.BrowserUtils;
import org.jeecg.common.util.TokenUtils;
import org.jeecg.common.util.oConvertUtils;
import org.jeecg.modules.online.desform.entity.DesignForm;
import org.jeecg.modules.online.desform.entity.DesignFormData;
import org.jeecg.modules.online.desform.excel.converter.ConvertUtil;
import org.jeecg.modules.online.desform.service.IDesignFormDataService;
import org.jeecg.modules.online.desform.service.IDesignFormService;
import org.jeecg.modules.online.desform.util.DesformImportExcelHandler;
import org.jeecg.modules.online.desform.util.DesformUtils;
import org.jeecg.modules.online.desform.util.convert.ConvertItem;
import org.jeecg.modules.online.desform.vo.excel.DesformWidgetList;
import org.jeecg.modules.online.desform.vo.widget.DesformWidget;
import org.jeecgframework.poi.excel.ExcelExportUtil;
import org.jeecgframework.poi.excel.ExcelImportUtil;
import org.jeecgframework.poi.excel.entity.ExportParams;
import org.jeecgframework.poi.excel.entity.ImportParams;
import org.jeecgframework.poi.excel.entity.params.ExcelExportEntity;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
import java.util.*;

/**
 * @Description: 表单设计数据
 * @Author: jeecg-boot
 * @Date: 2019-05-16
 * @Version: V1.0
 */
@RestController("designFormDataController")
@RequestMapping("/desform/data")
@Slf4j
public class DesignFormDataController {

    private ISysBaseAPI sysBaseAPI;

    private IDesignFormDataService designFormDataService;
    private IDesignFormService designFormService;

    @Autowired
    public DesignFormDataController(ISysBaseAPI sysBaseAPI, IDesignFormDataService designFormDataService, IDesignFormService designFormService) {
        this.sysBaseAPI = sysBaseAPI;
        this.designFormDataService = designFormDataService;
        this.designFormService = designFormService;
    }

	@Value("${jeecg.path.upload}")
	private String upLoadPath;

	@Value(value="${jeecg.uploadType}")
	private String uploadType;

    /**
     * 分页列表查询（主表）
     *
     * @param designFormData
     * @param pageNo
     * @param pageSize
     * @param request
     * @return
     */
    @GetMapping(value = "/list")
    public Result<?> list(DesignFormData designFormData,
            @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
            @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
            @RequestParam(name = "desformCode") String desformCode,
            @RequestParam(name = "superQuery", required = false, defaultValue = "{}") String superQuery,
            HttpServletRequest request) throws UnsupportedEncodingException {
        String username = JwtUtil.getUserNameByToken(request);
        QueryWrapper<DesignFormData> queryWrapper = QueryGenerator.initQueryWrapper(designFormData, request.getParameterMap());
        queryWrapper.orderByDesc("create_time");
        return designFormDataService.queryPage(desformCode, pageNo, pageSize, queryWrapper, superQuery, username);
    }

    /**
     * 添加
     *
     * @param designFormData
     * @return
     */
    @PostMapping(value = "/add")
    public Result add(@RequestBody DesignFormData designFormData) {
        return designFormDataService.addOne(designFormData);
    }

    /**
     * 编辑
     *
     * @param designFormData
     * @return
     */
    @PutMapping(value = "/edit")
    public Result edit(@RequestBody DesignFormData designFormData) {
        return designFormDataService.editOne(designFormData);
    }

    /**
     * 通过id删除
     *
     * @param id
     * @return
     */
    @DeleteMapping(value = "/delete")
    public Result delete(@RequestParam(name = "id") String id, HttpServletRequest request) {
        return designFormDataService.deleteOne(id, TokenUtils.getTokenByRequest(request));
    }

    /**
     * 批量删除
     *
     * @param ids
     * @return
     */
    @DeleteMapping(value = "/deleteBatch")
    public Result<DesignFormData> deleteBatch(@RequestParam(name = "ids") String ids, HttpServletRequest request) {
        Result<DesignFormData> result = new Result<DesignFormData>();
        if (ids == null || "".equals(ids.trim())) {
            result.error500("参数不识别！");
        } else {
            this.designFormDataService.deleteBatchMain(Arrays.asList(ids.split(",")), TokenUtils.getTokenByRequest(request));
            result.success("删除成功!");
        }
        return result;
    }

    /**
     * 通过id查询
     *
     * @param id
     * @return
     */
    @GetMapping(value = "/queryById")
    public Result<DesignFormData> queryById(@RequestParam(name = "id", required = true) String id) {
        Result<DesignFormData> result = new Result<DesignFormData>();
        DesignFormData designForm = designFormDataService.getById(id);
        if (designForm == null) {
            result.error500("未找到对应数据");
        } else {
            result.setResult(designForm);
            result.setSuccess(true);
        }
        return result;
    }

    /**
     * 通过id查询
     *
     * @param id
     * @return
     */
    @GetMapping(value = "/queryDesignFormDataByMainId")
    public Result<List<DesignFormData>> queryDesignFormDataListByMainId(@RequestParam(name = "id", required = true) String id) {
        Result<List<DesignFormData>> result = new Result<List<DesignFormData>>();
        List<DesignFormData> designFormDataList = designFormDataService.selectByMainId(id);
        result.setResult(designFormDataList);
        result.setSuccess(true);
        return result;
    }

    /**
     * 导出 Excel
     *
     * @param desformCode
     * @param request
     * @param response
     */
    @GetMapping(value = "/exportXls/{desformCode}")
    public void exportXls(DesignFormData designFormData,
            @PathVariable("desformCode") String desformCode,
            @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
            @RequestParam(name = "selectionIds", required = false) String selectionIds,
            @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
            @RequestParam(name = "superQuery", required = false, defaultValue = "{}") String superQuery,
            HttpServletRequest request, HttpServletResponse response) throws Exception {
        //1. 查询表单信息
        DesignForm designForm = designFormService.getByCode(desformCode);
        if (designForm == null) {
            return;
        }
        String desformName = designForm.getDesformName();
        // 组件列表
        DesformWidgetList widgetList = DesformUtils.getDesformWidgetListByEntity(designForm);
        assert widgetList != null;
        // 2. 查询数据
        QueryWrapper<DesignFormData> queryWrapper = QueryGenerator.initQueryWrapper(designFormData, request.getParameterMap());
        // 选择行导出
        if (oConvertUtils.isNotEmpty(selectionIds)) {
            queryWrapper.in("id", Arrays.asList(selectionIds.split(",")));
        }
        String username = JwtUtil.getUserNameByToken(request);
        //设置为此值则查询所有数据
        pageSize = -521;
        Result<IPage<DesignFormData>> designFormDataPageResult = designFormDataService.queryPage(desformCode, pageNo, pageSize, queryWrapper, superQuery, username);
        List<DesignFormData> designFormDataParentList = new ArrayList<>();
        if (designFormDataPageResult.getResult() != null) {
            designFormDataParentList = designFormDataPageResult.getResult().getRecords();
        }
        // 导出数据
        List<Map<String, Object>> designFormDataList = new ArrayList<>(designFormDataParentList.size());
        for (DesignFormData dataItem : designFormDataParentList) {
            String dataJSONString = dataItem.getDesformDataJson();
            if (StringUtil.isNotBlank(dataJSONString)) {
                designFormDataList.add(JSON.parseObject(dataJSONString).getInnerMap());
            }
        }
        // 【主表】EXCEL导出数据转换器
        ConvertUtil.doConvertDataList(ConvertUtil.out, designFormDataList, widgetList.main);
        //3. 封装导出列对应title实体
        List<ExcelExportEntity> entityList = DesformUtils.convertToExportEntity(widgetList.main);

        //4. 处理子表
        for (String key : widgetList.sub.keySet()) {
            List<DesformWidget> subWidgetList = widgetList.sub.get(key);
            // 取出并解码（子表进行了URLEncoder编码）子表数据
            for (Map<String, Object> mainData : designFormDataList) {
                Object subDataObj = mainData.get(key);
                List<Map<String, Object>> subDataList = new ArrayList<>();
                if (!oConvertUtils.isEmpty(subDataObj)) {
                    JSONArray subDataArray = JSON.parseArray(URLDecoder.decode(subDataObj.toString(), "UTF-8"));
                    for (int i = 0; i < subDataArray.size(); i++) {
                        subDataList.add(subDataArray.getJSONObject(i).getInnerMap());
                    }
                }
                // 翻译转换子表数据
                ConvertUtil.doConvertDataList(ConvertUtil.out, subDataList, subWidgetList);
                // 覆盖编码的数据
                mainData.put(key, subDataList);
            }
            List<ExcelExportEntity> subEntityList = DesformUtils.convertToExportEntity(subWidgetList);
            // 将子表信息添加到主导出实体中
            ExcelExportEntity subEntity = new ExcelExportEntity(widgetList.subNames.get(key), key);
            subEntity.setList(subEntityList);
            entityList.add(subEntity);
        }

        //4. 导出workbook
        Workbook workbook = ExcelExportUtil.exportExcel(new ExportParams(null, desformName), entityList, designFormDataList);
        //5. response写出
        OutputStream outputStream = null;
        try {
            response.setContentType("application/x-msdownload;charset=utf-8");

            String browse = BrowserUtils.checkBrowse(request);

            if ("MSIE".equalsIgnoreCase(browse.substring(0, 4))) {
                response.setHeader("content-disposition", "attachment;filename=" + java.net.URLEncoder.encode(desformName, "UTF-8") + ".xls");
            } else {
                String newTitle = new String(desformName.getBytes(StandardCharsets.UTF_8), "ISO8859-1");
                response.setHeader("content-disposition", "attachment;filename=" + newTitle + ".xls");
            }

            outputStream = response.getOutputStream();
            workbook.write(outputStream);
            response.flushBuffer();
        } catch (Exception e) {
            log.error("--通过流的方式获取文件异常--" + e.getMessage(), e);
        } finally {
            if (outputStream != null) {
                try {
                    outputStream.close();
                } catch (IOException e) {
                    log.error(e.getMessage(), e);
                }
            }
        }
    }

    @PostMapping(value = "/importXls/{desformCode}")
    public Result importXls(@PathVariable("desformCode") String desformCode, HttpServletRequest request) {
        String token = TokenUtils.getTokenByRequest(request);
        long beginTime = System.currentTimeMillis();
        try {
            //1. 查询表单信息
            DesignForm designForm = designFormService.getByCode(desformCode);
            if (designForm == null) {
                return Result.error("无法导入不存在的表单");
            }
            String desformName = designForm.getDesformName();
            JSONArray dataList = DesformUtils.getDataList(designForm);
            Map<String, ConvertItem> converters = DesformUtils.getConvertersIfNeed(dataList);
            // 组件列表
            DesformWidgetList widgetList = DesformUtils.getDesformWidgetListByDataList(dataList);
            assert widgetList != null;

            //2. 获取上传文件
            MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
            Map<String, MultipartFile> fileMap = multipartRequest.getFileMap();

            //3. 遍历上传文件
            for (Map.Entry<String, MultipartFile> entity : fileMap.entrySet()) {
                // 获取单个上传文件
                MultipartFile file = entity.getValue();
                ImportParams params = new ImportParams();
                // params.setDataHanlder(new DesformExcelHandler(dataList));
                List<Map<String, Object>> importDataList = ExcelImportUtil.importExcel(file.getInputStream(), Map.class, params);
                log.info("[表单设计器导入] 原始数据：" + JSON.toJSONString(importDataList));

                if (importDataList != null) {
                    DesformImportExcelHandler handler = new DesformImportExcelHandler(widgetList, importDataList, converters);
                    log.info("[表单设计器导入] 实际数据：" + JSON.toJSONString(handler.saveData));
                    designFormDataService.saveBatchByImport(designForm, handler.saveData, token);
                } else {
                    log.error("识别模版数据错误");
                }
            }
            log.info("= = = = = 表单设计器（" + desformName + "）导入数据完成，耗时:" + (System.currentTimeMillis() - beginTime) + "ms = = = = =");
            return Result.ok("导入成功");
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return Result.error(e.getMessage());
        }
    }

    /**
     * 反向转换字典值
     */
    private void reverseDictByValue(JSONObject mainData, JSONArray dataList) {
        Map<String, List<DictModel>> dictMap = new HashMap<>();
        DesformUtils.recursiveAllWidget(dataList, (type, item, parent) -> {
            // 过滤
            if (!DesformUtils.isNotDataWidget(type)) {
                String model = item.getString("model");
                Object valueObj = mainData.get(model);
                String value;
                if (valueObj != null && StringUtil.isNotBlank(value = valueObj.toString())) {
                    JSONObject options = item.getJSONObject("options");
                    String dictCode = options.getString("dictCode");
                    if (StringUtil.isNotBlank(dictCode)) {
                        List<DictModel> dicDataList = dictMap.get(dictCode);
                        if (dicDataList == null) {
                            dicDataList = sysBaseAPI.queryDictItemsByCode(dictCode);
                            dictMap.put(dictCode, dicDataList);
                        }
                        for (DictModel dictItem : dicDataList) {
                            if (value.equals(dictItem.getText())) {
                                mainData.put(model, dictItem.getValue());
                            }
                        }
                    }
                }
            }
        });
    }

}
